package org.example.mallchat.service.impl;

import cn.hutool.core.bean.BeanUtil;
import org.example.mallchat.adapter.ResultVoBuilder;
import org.example.mallchat.cache.ItemCacheHandler;
import org.example.mallchat.common.event.UserRegisterEvent;
import org.example.mallchat.dao.UserBackpackDao;
import org.example.mallchat.dao.UserDao;
import org.example.mallchat.domain.entity.ItemConfig;
import org.example.mallchat.domain.entity.User;
import org.example.mallchat.domain.entity.UserBackpack;
import org.example.mallchat.domain.enums.ItemTypeEnum;
import org.example.mallchat.domain.enums.UserBackPackEnum;
import org.example.mallchat.domain.vo.response.UserBadgeRep;
import org.example.mallchat.domain.vo.response.UserInfoRep;
import org.example.mallchat.exception.ErrorCode;
import org.example.mallchat.exception.ThrowUtils;
import org.example.mallchat.service.UserService;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author: zzh
 * @date: 2024/12/22 22:48:36
 * @version: 1.0
 */
@Service
public class UserServiceImpl implements UserService {
    @Resource
    private UserDao userDao;

    @Resource
    private UserBackpackDao userBackpackDao;

    @Resource
    private ItemCacheHandler cacheHandler;

    @Resource
    private ApplicationEventPublisher applicationEventPublisher;

    @Override
    @Transactional// 事务注解 还需要开启事务
    public void register(String openId) {
        User user = new User();
        user.setOpenId(openId);
        userDao.save(user);
        // 发放一个改名卡 （事件）
        applicationEventPublisher.publishEvent(new UserRegisterEvent(this,user));
    }

    @Override
    public UserInfoRep getUserInfo(String uid) {
        ThrowUtils.throwIf(uid == null, ErrorCode.NOT_LOGIN_ERROR);
        // 获取用户信息
        User user = userDao.getById(uid);
        // 获取背包表中的改名卡的数量（该用户）
        int renameCardCount = userBackpackDao.getRenameCardCount(uid, UserBackPackEnum.MODIFY_NAME_CARD.getId());
        // 封装返回值
        UserInfoRep userInfoRep = BeanUtil.copyProperties(user, UserInfoRep.class);
        userInfoRep.setRenameCardNum(renameCardCount);
        return userInfoRep;
    }

    @Override
    @Transactional// 事务注解 还需要开启事务
    public void modifyUserName(String uid, String userName) {
        ThrowUtils.throwIf(uid == null, ErrorCode.NOT_LOGIN_ERROR);
        // 检查名字长度是否合法
        ThrowUtils.throwIf(userName.isEmpty() || userName.length() > 8, ErrorCode.NAME_VALIDATE_ERROR);
        // 检查改名卡是否足够
        int renameCardCount = userBackpackDao.getRenameCardCount(uid, UserBackPackEnum.MODIFY_NAME_CARD.getId());
        ThrowUtils.throwIf(renameCardCount <= 0, ErrorCode.NAME_CARD_NOT_ENOUGH);
        // 修改用户名
        userDao.modifyUserNameReduceCardCount(uid, userName);
        // 扣除改名卡
        userBackpackDao.reduceCardCount(uid, UserBackPackEnum.MODIFY_NAME_CARD.getId());
    }

    /**
     * 获取用户的徽章列表
     * 注意还要进行排序!
     * @param uid
     * @return
     */
    @Override
    public List<UserBadgeRep> getBadgeList(String uid) {
        ThrowUtils.throwIf(uid == null, ErrorCode.NOT_LOGIN_ERROR);
        // 获取用户所有的徽章// 我们采用注解@Cacheable 来缓存用户的徽章信息，避免频繁访问数据库
        List<ItemConfig> itemConfigList = cacheHandler.getItemConfigListByType(ItemTypeEnum.BADGE.getType());
        // 查询该用户拥有的徽章
        List<UserBackpack> userBackpackList = userBackpackDao.getBadgeList(uid,itemConfigList.stream().map(ItemConfig::getId).collect(Collectors.toList()));
        // 查询用户所带的徽章
        User user = userDao.getById(uid);
        // 封装返回值
        return ResultVoBuilder.buildUserBadgeList(itemConfigList, userBackpackList, user);
    }

    /**
     * 佩戴徽章
     * @param uid
     * @param wearingItemId
     * @return
     */
    @Override
    public Void wearBadge(String uid, Long wearingItemId) {
        ThrowUtils.throwIf(uid == null, ErrorCode.NOT_LOGIN_ERROR);
        // 查询该徽章是否存在
        List<ItemConfig> itemConfigListByType = cacheHandler.getItemConfigListByType(ItemTypeEnum.BADGE.getType());
        long count = itemConfigListByType.stream().filter(itemConfig -> itemConfig.getId().equals(wearingItemId)).count();
        ThrowUtils.throwIf(count <= 0, ErrorCode.BADGE_NOT_EXIST);
        // 佩戴徽章
        userDao.wearBadge(uid, wearingItemId);
        // 修改物品状态
        userBackpackDao.wearBadge(uid, wearingItemId);
        return null;
    }
}
